/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package encaps.entities;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import javax.ejb.CreateException;
import javax.ejb.EJBException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;
import javax.ejb.FinderException;
import javax.ejb.NoSuchEntityException;
import javax.ejb.ObjectNotFoundException;
import javax.ejb.RemoveException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import encaps.utils.DatabaseUtil;
import encaps.utils.StringUtil;

/**
 *
 * @author Дима
 */
public class Person implements EntityBean {

    public static final String TABLE_NAME = "Person";
    public static final String NAME = "name";
    public static final String BIOGRAPHY = "biography";
    public static final String PIC = "pic";

    private EntityContext context;
    private DataSource dataSource;
    private boolean isEdited;
    
    private Long id;
    private String name;
    private String photo;
    private String bio;

    public void setEntityContext(EntityContext aContext) {
        context = aContext;
        try {
            dataSource = DatabaseUtil.getDataSource();
            isEdited = false;
        } catch(NamingException e) {
            throw new EJBException("DataSource lookup error", e);
        }
    }
    
    public void unsetEntityContext() {
        context = null;
    }    

    public Long ejbCreate(String name, String photo, String bio) throws CreateException {
        PreparedStatement insertValuesQuery = null;
        PreparedStatement selectIdQuery = null;
        Connection conn = null;
        try {
            this.photo = photo;
            this.name = name;
            this.bio = bio;
            conn = dataSource.getConnection();
            insertValuesQuery = conn.prepareStatement("INSERT INTO person(name, pic, biography) VALUES(?, ?, ?)");
            insertValuesQuery.setString(1, name);
            insertValuesQuery.setString(2, photo);
            insertValuesQuery.setString(3, bio);
            if(insertValuesQuery.executeUpdate() != 1) {
                throw new CreateException("Insertion error");
            }
            selectIdQuery = conn.prepareStatement("SELECT LAST_INSERT_ID()");
            ResultSet rs = selectIdQuery.executeQuery();
            if(!rs.next()) {
                throw new CreateException("Insertion error");
            }
            id = rs.getLong(1);
            
            isEdited = false;
            return id;
        } catch(Exception ex) {
            throw new EJBException("Error in Person.ejbCreate method", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, selectIdQuery);
            DatabaseUtil.closeConnection(null, insertValuesQuery);
        }

    }

    public void ejbPostCreate(String name, String photo, String bio) throws CreateException {
    }

    public void ejbActivate() {
        //doin' nothing
    }
    
    public void ejbPassivate() {
        //doin' nothing
    }
    
    public void ejbRemove() throws RemoveException {
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            ps = conn.prepareStatement("DELETE FROM person WHERE id=?");
            ps.setLong(1, id);
            if(ps.executeUpdate() < 1) {
                throw new RemoveException("Deletion error. Id="+id);
            }
            isEdited = false;
        } catch(SQLException ex) {
            throw new EJBException("Error in Person.ejbRemove method", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, ps);
        }
    }
    
    
    public void ejbLoad() {
        id = (Long) context.getPrimaryKey();
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            ps = conn.prepareStatement("SELECT name, biography, pic FROM person WHERE id=?");
            ps.setLong(1, id);
            ResultSet rs = ps.executeQuery();
            if(!rs.next()) {
                throw new NoSuchEntityException("No person found by id = " + id);
            }
            photo = rs.getString(PIC);
            name = rs.getString(NAME);
            bio = rs.getString(BIOGRAPHY);
            isEdited = false;
        } catch(SQLException ex) {
            throw new EJBException("Error in Person.ejbLoad method", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, ps);
        }
    }
    
    public void ejbStore() {
        if(!isEdited) {
            return;
        }
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            ps = conn.prepareStatement("UPDATE person SET name=?, pic=?, biography=? WHERE id=?");
            ps.setString(1, name);
            ps.setString(2, photo);
            ps.setString(3, bio);
            ps.setLong(4, id);
            if(ps.executeUpdate() < 1) {
                throw new NoSuchEntityException("No person found by id = " + id);
            }
            isEdited = false;
        } catch(SQLException ex) {
            throw new EJBException("Error in Person.ejbStore method", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, ps);
        }
    }
    
    public java.lang.Long ejbFindByPrimaryKey(Long key) throws ObjectNotFoundException {
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            ps = conn.prepareStatement("SELECT id FROM person WHERE id=?;");
            ps.setLong(1, key);
            ResultSet rs = ps.executeQuery();
            if(!rs.next()) {
                throw new ObjectNotFoundException("No person found by primary key = " + key);
            }
            return key;
        } catch(SQLException ex) {
            throw new EJBException("Error in Person.ejbFindByPrimaryKey method", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, ps);
        }
    }

    public Collection ejbFindByParameters(String name, String bio) throws FinderException {
        HashMap criteria = new HashMap();
        if(!StringUtil.isEmpty(name)) criteria.put(NAME, name);
        if(!StringUtil.isEmpty(bio)) criteria.put(BIOGRAPHY, bio);
        if(criteria.isEmpty()) {
            throw new FinderException("Person search criteria are empty");
        }

        PreparedStatement ps = null;
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            String searchQuery = StringUtil.constructSelectQuery(TABLE_NAME, "id", criteria);
            System.out.println("s q:" + searchQuery);
            ps = conn.prepareStatement(searchQuery);
            Collection keys = new LinkedList();
            ResultSet rs = ps.executeQuery();
            while(rs.next()) {
                keys.add(rs.getLong(1));
            }
            return keys;
        } catch(SQLException ex) {
            throw new EJBException("Error in Person.ejbFindByParameters method", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, ps);
        }
    }

    public Collection ejbFindAll() {
        PreparedStatement ps = null;
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
            ps = conn.prepareStatement("SELECT id FROM Person");
            Collection keys = new LinkedList();
            ResultSet rs = ps.executeQuery();
            while(rs.next()) {
                keys.add(rs.getLong(1));
            }
            return keys;
        } catch(SQLException ex) {
            throw new EJBException("Error in Person.ejbFindAll method", ex);
        } finally {
            DatabaseUtil.closeConnection(conn, ps);
        }
    }


    public Long getId() {
        return id;
    }
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        isEdited = true;
    }

    public String getPhoto() {
        return photo;
    }

    public void setPhoto(String photo) {
        this.photo = photo;
        isEdited = true;
    }

    public String getBio() {
        return bio;
    }

    public void setBio(String bio) {
        this.bio = bio;
        isEdited = true;
    }
    
    public String stringRepresentation() {
        StringBuilder sb = new StringBuilder();
        sb.append(getClass().getName());
        sb.append(": [");
        sb.append("id=");
        sb.append(id);
        sb.append(", name=");
        sb.append(name);
        sb.append(", bio=");
        sb.append(bio);
        sb.append(", photo=");
        sb.append(photo);
        sb.append("]");
        return sb.toString();
    }
}
